package self.example.explore.util;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static self.example.explore.constant.DataSourceConfigInfo.*;

/**
 * @author 1.
 * @version 1.0
 * @description: 连接数据源并获取数据源信息
 * @date 2023/4/1 9:53
 */
/*
*  TODO 优化：
*           1. 优化对象锁的选择：reentrantLock?
*           2. 优化连接，改为从连接池中取
*           3. 优化工具类，加入策略模式：是否配置连接池?
*           4. 将连接操作封装成内部类? 重构获取连接和释放连接的逻辑。
*           5. boolean closeRes = closeConnectCannel(); // 定时重试?
* */
public final class NonPoolDataSourceInfoParser {
    //数据源连接
    // TODO 双重检查下需要加上 volatile
    private volatile Connection connection;

    /**
     *  注册驱动
     */
    static {
        try {
            Class.forName(DRIVER_CLASS_NAME);
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
    }

    //获取数据源连接
    private boolean getConnect(){
        if(connection == null){
            synchronized (NonPoolDataSourceInfoParser.class) {
                if(connection == null){
                    try {
                        connection = DriverManager.getConnection(URL, USER_NAME, PASS_WORD);
                    } catch (SQLException e) {
                        System.out.println("failed to get connection, may be is cause: " + e.getMessage());
                        return false;
                    }
                }
            }
        }
        return true;
    }

    //断开数据源连接
    private boolean closeConnectChannel(){
        if(connection != null){
            synchronized (NonPoolDataSourceInfoParser.class) {
                if(connection != null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        System.out.println("failed to close channel used to connect, may be is cause: " + e.getMessage());
                        return false;
                    }
                }
            }
        }
        return true;
    }


    /**
     * 获取数据库下的所有表名
     */
    public List<String> getTableNames() {
        List<String> tableNames = new ArrayList<>();
        if(! getConnect())
            return null;
        ResultSet rs = null;
        try {
            //获取数据库的元数据
            DatabaseMetaData db = connection.getMetaData();
            //从元数据中获取到所有的表名
            rs = db.getTables(null, null, null, new String[] { "TABLE" });
//            System.out.println(rs);
            while(rs.next()) {
//                tableNames.add(rs.getString(3));
                if(Objects.equals(rs.getString(1), "db1")){ // TODO 指定数据库名
                    tableNames.add(rs.getString(3));
                }
            }
        } catch (SQLException e) {
            System.out.println("getTableNames failure: " + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                if(rs != null)
                    rs.close();
                boolean closeRes = closeConnectChannel();//TODO 定时重试?
                System.out.println("连接关闭状态: " + closeRes);
            } catch (SQLException e) {
                System.out.println("close ResultSet failure: " + e.getMessage());
                e.printStackTrace();
            }
        }
        return tableNames;
    }

//    public static void main(String[] args) {
//        DataSourceSingleConnectAndGet dc = new DataSourceSingleConnectAndGet();
//        System.out.println(dc.getTableNames());
//    }
}
